/**
 * \class GenNonTerminal.h /GenProg/Generator/Exp/GenNonTerminal.h
 *
 *  \date 5 jul 2012
 *  \author calle
 *  
 *  \brief Generates Non terminal Expressions.
 */

#ifndef GENNONTERMINAL_H_
#define GENNONTERMINAL_H_
#include <Generator/context/IContext.h>
#include <Helpers/ExpRegistry.h>
#include <Generator/TerminalState.h>
#include <AbsSyn/TypeEnum.h>

/**
 *  \brief Generates a Non-terminal expression which terminates with constants (eventually)
 *
 *  See sequence diagram GenNonTerminal_seq.dia
 *
 */
class GenNonTerminal {
public:
	/**
	 * \brief constructor
	 *
	 * @see ExpRegistry
	 * @see ExpressionTyp
	 * @see IContext
	 *
	 * @param registry the registry in which we get all the available non-terminals.
	 * @param type of expression (bool,int ....)
	 * @param currentContext The context in which this is working in.
	 */
	GenNonTerminal(const ExpRegistry& registry,const TypeEnum& type,IContext* currentContext, unsigned int depth);

	/**
	 * \brief Destructor
	 */
	virtual ~GenNonTerminal();

	/**
	 * \brief genNonTerminal creates a non-terminal with termination
	 *
	 * @return IExp
	 */
	AbsSyn::IExpPtr genNonTerminal();

private:
	const ExpRegistry& m_Registry;
	TypeEnum m_Type;
	IContext* m_currentContext;
	unsigned int m_Depth;
	/**
	 * \brief list of Generation pointers
	 *
	 * Is used to a list in which the types are matching.
	 */
	typedef list<ExpRegistry::TGenPtr> GenPtrList;

private: // private methods
	/**
	 * \brief This method randomly chooses one of the genration method from the list provided.
	 *
	 *
	 * @param list
	 * @return randomly choosen generation function.
	 */
	ExpRegistry::TGenPtr randChooseGenExpFun(const ExpRegistry::TGenFunTypeMap& list) const;

	/**
	 * \brief will generate and create a terminated expression
	 *
	 * By using the ExpRegistry genaration function to create
	 * a new expression. If that expression needs other arguments,
	 * then create those terminated expressions first, and then finally create
	 * the last expression using the before created once.
	 *
	 * @param genFun
	 * @return Full worthy expression that terminates
	 */
	AbsSyn::IExpPtr constructExp( const ExpRegistry::TGenPtr& genFun ) const;
	/**
	 * \brief Constructs a new list of available IGenExp for the m_Type.
	 *
	 * Not all IGenExp are available for a certain type.
	 * This method filters out the ones that are. For example
	 * add expression does not make any sense for booleans.
	 *
	 *
	 * @param genMap
	 * @return list of IGenExp of matching type
	 */
	GenPtrList getListWithMatchingType(const ExpRegistry::TGenFunTypeMap& genMap) const;
};

#endif /* GENNONTERMINAL_H_ */
